﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XNA_TD.Menue
{
    public class UpgradeMenueInfo
    {
        public string nextDmg, nextRange, nextFireRate, kosten, text;
        public Vector2 pos;
        public Rectangle rect;
        public int id;

        public UpgradeMenueInfo(Vector2 pos, LvlInfo info, int id)
        {
            this.id = id;
            kosten = info.nextUpgrades[id].preis.ToString();
            text = info.nextUpgrades[id].text + ": " + kosten;
            var offset = DebugInfo.Instance.debugFont.MeasureString(text);
            this.pos = pos;
            this.rect = new Rectangle((int)pos.X, (int)pos.Y, (int)offset.X, (int)offset.Y);
            nextDmg = "+" + (Math.Round(info.nextUpgrades[id].attackDmg - info.attackDmg, 1)).ToString();
            nextRange = "+" + (Math.Round(info.nextUpgrades[id].attackRange - info.attackRange, 1)).ToString();
            nextFireRate = "+" + (Math.Round(info.nextUpgrades[id].fireRate - info.fireRate, 1)).ToString();
        }

        public void setX(int X)
        {
            pos.X = X;
            rect.X = X;
        }

        public void setY(int Y)
        {
            pos.Y = Y;
            rect.Y = Y;
        }
    }

    public class UpgradeMenue : GUI, IRTT
    {
        RenderTarget2D renderTarget;
        Texture2D towerTexture;
        public Tower tower;
        Vector3 offset;
        static Texture2D bg = null;
        Vector2 rttPos;
        string currDmg, nextDmg, currRange, nextRange, currFireRate, nextFireRate, sellPreis;
        Vector2 dmg, range, fireRate, dmgNummer, rangeNummer, fireRateNummer, dmgUpdate, rangeUpdate, fireRateUpdate, sell;
        List<UpgradeMenueInfo> upgrade;
        Rectangle dmgRect, rangeRect, fireRateRect, sellRect;
        Color hover;

        public UpgradeMenue(Tower tower)
        {
            this.tower = tower;
            renderTarget = new RenderTarget2D(graphics.GraphicsDevice, 128, 128, false, graphics.GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24);
            if (bg == null)
            {
                bg = Content.Load<Texture2D>("Menue/upgrade");
            }
            upgrade = new List<UpgradeMenueInfo>(4);
            Reset();
        }

        private void Reset()
        {
            offset = new Vector3(-1, 1, 0) * 1.2f;
            size = new Rectangle(0, 30, bg.Width, bg.Height);
            rttPos = new Vector2(0, size.Y + 10);
            dmg = new Vector2(0, size.Y + 128 + 20);
            fireRate = new Vector2(0, dmg.Y + 15);
            range = new Vector2(0, fireRate.Y + 15);

            dmgNummer = new Vector2(0, size.Y + 128 + 20);
            fireRateNummer = new Vector2(0, dmg.Y + 15);
            rangeNummer = new Vector2(0, fireRate.Y + 15);

            dmgUpdate = new Vector2(0, size.Y + 128 + 20);
            fireRateUpdate = new Vector2(0, dmg.Y + 15);
            rangeUpdate = new Vector2(0, fireRate.Y + 15);

            dmgRect = new Rectangle(0, size.Y + 128 + 20, 0, 0);
            fireRateRect = new Rectangle(0, (int)dmg.Y + 15, 0, 0);
            rangeRect = new Rectangle(0, (int)fireRate.Y + 15, 0, 0);

            int Y = (int)range.Y + 20;
            upgrade.Clear();
            for (int id = 0; id < tower.lvlInfo.nextUpgrades.Count; id++)
            {
                upgrade.Add(new UpgradeMenueInfo(new Vector2(0, Y), tower.lvlInfo, id));
                Y += 20;
            }
            Y += (3 - upgrade.Count) * 20;
            sell = new Vector2(0, Y);
            sellRect = new Rectangle(0, Y, 0, 0);

            hover = Color.YellowGreen;
            UpdateData(-1);
        }

        private void UpdateData(int id)
        {
            double currDmgVal = Math.Round(tower.lvlInfo.attackDmg, 1);
            double currRangeVal = Math.Round(tower.lvlInfo.attackRange, 1);
            double currFireRateVal = Math.Round(tower.lvlInfo.fireRate, 1);

            currDmg = currDmgVal.ToString();
            currRange = currRangeVal.ToString();
            currFireRate = currFireRateVal.ToString();
            sellPreis = "Verkaufen fuer: " + tower.VerkaufsPreis().ToString();

            if (id < 0 || id > tower.lvlInfo.nextUpgrades.Count)
            {
                nextDmg = "";
                nextRange = "";
                nextFireRate = "";
            }
            else
            {
                nextDmg = "+" + (Math.Round(tower.lvlInfo.nextUpgrades[id].attackDmg, 1) - currDmgVal).ToString();
                nextRange = "+" + (Math.Round(tower.lvlInfo.nextUpgrades[id].attackRange, 1) - currRangeVal).ToString();
                nextFireRate = "+" + (Math.Round(tower.lvlInfo.nextUpgrades[id].fireRate, 1) - currFireRateVal).ToString();
            }
            Resize();
        }

        public override void Draw()
        {
            var depthStencilState = graphics.GraphicsDevice.DepthStencilState;
            spriteBatch.Begin();
            spriteBatch.Draw(bg, size, Color.White);
            spriteBatch.Draw(towerTexture, rttPos, Color.White);
            spriteBatch.DrawString(DebugInfo.Instance.debugFont, "DMG:", dmg, Color.Black);
            spriteBatch.DrawString(DebugInfo.Instance.debugFont, "Fire Rate:", fireRate, Color.Black);
            spriteBatch.DrawString(DebugInfo.Instance.debugFont, "Range:", range, Color.Black);

            spriteBatch.DrawString(DebugInfo.Instance.debugFont, currDmg, dmgNummer, Color.Black);
            spriteBatch.DrawString(DebugInfo.Instance.debugFont, currFireRate, fireRateNummer, Color.Black);
            spriteBatch.DrawString(DebugInfo.Instance.debugFont, currRange, rangeNummer, Color.Black);

            foreach (var info in upgrade)
            {
                if (MouseInside(info.rect))
                {
                    spriteBatch.DrawString(DebugInfo.Instance.debugFont, info.text, info.pos, hover);
                }
                else
                {
                    spriteBatch.DrawString(DebugInfo.Instance.debugFont, info.text, info.pos, Color.Black);
                }
                //spriteBatch.Draw(bg, info.rect, Color.Black);
            }

            spriteBatch.DrawString(DebugInfo.Instance.debugFont, nextDmg, dmgUpdate, hover);
            spriteBatch.DrawString(DebugInfo.Instance.debugFont, nextFireRate, fireRateUpdate, hover);
            spriteBatch.DrawString(DebugInfo.Instance.debugFont, nextRange, rangeUpdate, hover);
            if (MouseInside(sellRect))
            {
                spriteBatch.DrawString(DebugInfo.Instance.debugFont, sellPreis, sell, hover);
            }
            else
            {
                spriteBatch.DrawString(DebugInfo.Instance.debugFont, sellPreis, sell, Color.Black);
            }
            spriteBatch.End();
            graphics.GraphicsDevice.DepthStencilState = depthStencilState;

        }

        public Vector2 getPosition(string text)
        {
            var offset = DebugInfo.Instance.debugFont.MeasureString(text);
            offset.Y = 0;
            return offset;
        }

        public override void Resize()
        {
            size.X = graphics.GraphicsDevice.Viewport.Width - bg.Width;
            rttPos.X = size.X + 10;
            dmg.X = rttPos.X;
            fireRate.X = rttPos.X;
            range.X = rttPos.X;

            dmgNummer.X = rttPos.X + 90 - getPosition(currDmg).X;
            fireRateNummer.X = rttPos.X + 90 - getPosition(currFireRate).X;
            rangeNummer.X = rttPos.X + 90 - getPosition(currRange).X;

            dmgUpdate.X = rttPos.X + 128 - getPosition(nextDmg).X;
            fireRateUpdate.X = rttPos.X + 128 - getPosition(nextFireRate).X;
            rangeUpdate.X = rttPos.X + 128 - getPosition(nextRange).X;

            var offset = DebugInfo.Instance.debugFont.MeasureString(nextDmg);
            dmgRect.X = (int)dmgUpdate.X;
            dmgRect.Width = (int)offset.X;
            dmgRect.Height = (int)offset.Y;

            offset = DebugInfo.Instance.debugFont.MeasureString(nextFireRate);
            fireRateRect.X = (int)fireRateUpdate.X;
            fireRateRect.Width = (int)offset.X;
            fireRateRect.Height = (int)offset.Y;

            offset = DebugInfo.Instance.debugFont.MeasureString(nextRange);
            rangeRect.X = (int)rangeUpdate.X;
            rangeRect.Width = (int)offset.X;
            rangeRect.Height = (int)offset.Y;
            
            offset = DebugInfo.Instance.debugFont.MeasureString(sellPreis);
            for (int i = 0; i < upgrade.Count; i++)
            {
                upgrade[i].setX((int)rttPos.X);
            }
            sell.X = rttPos.X;
            sellRect.X = (int)rttPos.X;
            sellRect.Width = (int)offset.X;
            sellRect.Height = (int)offset.Y;
        }

        public override void Update()
        {
            base.Update();
            if (buttonPressed.MouseRightButtonPressed())
            {
                UnRegister(this);
                new BauMenue();
            }
            else if (!mouseInside && buttonPressed.MouseLeftButtonPressed())
            {
                SelectTowerToUpgrade();
            }
            else if(mouseInside)
            {
                foreach (var info in upgrade)
                {
                    if (MouseInside(info.rect))
                    {
                        UpdateData(info.id);
                        return;
                    }
                }
                UpdateData(-1);
            }
        }

        public override void MouseClick()
        {
            if (mouseInside)
            {
                foreach (var info in upgrade)
                {
                    if (MouseInside(info.rect))
                    {
                        tower.Upgrade(info.id);
                        Reset();
                        return;
                    }
                }
                if (MouseInside(sellRect))
                {
                    geld += tower.VerkaufsPreis();
                    UnRegister(tower);
                    UnRegister(this);
                    new BauMenue();
                    return;
                }
            }
        }

        public void RTT()
        {
            var rttViewMatrix = Matrix.CreateLookAt(tower.position + (Matrix.CreateTranslation(offset) * Matrix.CreateRotationY((float)gameTime.TotalGameTime.TotalMilliseconds / 1000f)).Translation, tower.position, Vector3.Up);
            float aspect = graphics.GraphicsDevice.DisplayMode.AspectRatio;
            var rttProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(60),
                aspect,
                .1f,
                20f);
            shader.Parameters["ViewProjection"].SetValue(rttViewMatrix * rttProjectionMatrix);

            graphics.GraphicsDevice.SetRenderTarget(renderTarget);
            graphics.GraphicsDevice.Clear(Color.Black);
            terrain.Draw();
            foreach (var to in gameManager.getRenderList(Priority.Tower))
            {
                var t = to as Tower;
                if (t != null)
                {
                    if (Math.Abs(tower.position.X - t.position.X) <= 5 &&
                        Math.Abs(tower.position.Z - t.position.Z) <= 5)
                    {
                        t.Draw();
                    }
                }
            }
            foreach (var to in gameManager.getRenderList(Priority.Einheit))
            {
                var t = to as Unit;
                if (t != null)
                {
                    if (Math.Abs(tower.position.X - t.position.X) <= 5 &&
                        Math.Abs(tower.position.Z - t.position.Z) <= 5)
                    {
                        t.Draw();
                    }
                }
            }
            towerTexture = (Texture2D)renderTarget;
            kamera.UpdateShader();
        }
    }
}
